package com.carkeeper.user.service.impl;

import com.carkeeper.user.dao.EmployeeMapper;
import com.carkeeper.user.dao.MenuDao;
import com.carkeeper.user.dao.PermissionDao;
import com.carkeeper.user.dao.RoleDao;
import com.carkeeper.user.pojo.Employee;
import com.carkeeper.user.pojo.Menu;
import com.carkeeper.user.pojo.Permission;
import com.carkeeper.user.pojo.Role;
import com.carkeeper.user.service.RoleService;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import javax.management.relation.RoleUnresolved;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @ClassName RoleServiceImpl
 * @Description TODO
 * @Author yangbin
 * @Date 2020/11/23 14:28
 * @Version 1.0
 */

@Service
@Transactional
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleDao roleDao;
    @Autowired
    private PermissionDao permissionDao;
    @Autowired
    private MenuDao menuDao;
    @Autowired
    private EmployeeMapper employeeMapper;

    /**
     * 新增角色
     * @param role
     * @param permissionIds
     * @param menuIds
     * @return
     */
    @Override
    public int addRole(Role role, Integer[] permissionIds, Integer[] menuIds) {
        // 判断角色是否存在
        Role selectOne = roleDao.selectOne(role);
        if (selectOne != null) {
            throw new RuntimeException("该角色已存在");
        }
        // 判断是否为角色授权
        if (permissionIds == null || permissionIds.length <= 0) {
            throw new RuntimeException("请为该角色授权");
        }

        // 判断是否为角色添加菜单
        if (menuIds == null || menuIds.length <= 0) {
            throw new RuntimeException("请为角色添加可操作的菜单");
        }
        int i = roleDao.insertSelective(role);
        // 为角色授权
        for (Integer permissionId : permissionIds) {
            permissionDao.addPermissionByRoleId(role.getId(), permissionId);
        }
        // 添加角色菜单表
        for (Integer menuId : menuIds) {
            System.out.println(role.getId());
            menuDao.addMenuListByRoleIdAndMenuId(role.getId(), menuId);
        }
        // 通过roleId查询一级菜单列表
        LinkedHashSet<Menu> menuList1 = menuDao.findMenuListByRoleId(role.getId());
        for (Menu menu : menuList1) {
            // 查询一级菜单对应的二级菜单
            List<Menu> childList2 = menuDao.findChildByParentRoleId(menu.getId());
            menu.setChildren(childList2);
        }
        return i;
    }

    /**
     * 删除角色
     * @param id
     * @return
     */
    @Override
    public int deleteById(Integer id) {
        // 查询角色权限中间表是否有数据
        Set<Permission> permissionList = permissionDao.findPermissionByRoleId(id);
        if (permissionList == null || permissionList.size() <= 0) {
            // 提示信息
            throw new RuntimeException("该账户异常，未授予权限");
        }
        // 先遍历删除角色权限中间表数据
        permissionDao.deletePermissionByRoleId(id);
        // 查询角色菜单表是否有数据
        LinkedHashSet<Menu> menuList = menuDao.findMenuListByRoleId(id);
        if (menuList == null && menuList.size() <= 0) {
            throw new RuntimeException("该账户异常，未授予可操作的一级菜单菜单");
        }
        // 先删除角色菜单表中的数据
        menuDao.deleteMenuListByRoleId(id);
        // // 遍历出一级菜单(二级菜单和角色没有直接联系不用管)
        // for (Menu menu : menuList) {
        //     // 得到二级菜单列表
        //     List<Menu> childList = menuDao.findChildByParentRoleId(menu.getId());
        //     if (childList == null && childList.size() <= 0) {
        //         throw new RuntimeException("该账户异常，未授予可操作的二级菜单");
        //     }
        //     // 遍历二级菜单得到二级菜单项
        //     for (Menu menu1 : childList) {
        //         // 删除每一个二级菜单项
        //         menuDao.deleteByPrimaryKey(menu1.getId());
        //     }
        //     // 删除一级菜单
        //     menuDao.deleteByPrimaryKey(menu.getId());
        // }

        return roleDao.deleteByPrimaryKey(id);
    }

    /**
     * 修改角色
     * @param role
     * @param permissionIds
     * @param menuIds
     * @return
     */
    @Override
    public int updateRole(Role role, Integer[] permissionIds, Integer[] menuIds) {
        // 判断角色是否存在
        Role selectOne = roleDao.selectOne(role);
        if (selectOne == null) {
            throw new RuntimeException("该角色不存在, 无法修改");
        }
        // 角色存在，先删除角色权限中间表的数据
        int i = permissionDao.deletePermissionByRoleId(role.getId());
        int i1 = menuDao.deleteMenuListByRoleId(role.getId());
        if (i <= 0 || i1 <= 0) {
            throw new RuntimeException("删除角色对应的权限或者菜单失败");
        }
        // 为角色重新授权
        for (Integer permissionId : permissionIds) {
            permissionDao.addPermissionByRoleId(role.getId(), permissionId);
        }
        // 为角色重新添加菜单
        for (Integer menuId : menuIds) {
            menuDao.addMenuListByRoleIdAndMenuId(role.getId(), menuId);
        }
        return roleDao.updateByPrimaryKeySelective(role);
    }

    /**
     * 根据id查询角色
     * @param id
     * @return
     */
    @Override
    public Role findById(Integer id) {
        // 查找对应的角色
        Role role = roleDao.selectByPrimaryKey(id);
        if (role == null) {
            throw new RuntimeException("该角色不存在，请检查检索条件是否正确");
        }
        // 通过角色id获取对应权限
        Set<Permission> permissionSet = permissionDao.findPermissionByRoleId(role.getId());
        if (permissionSet != null && permissionSet.size() > 0) {
            // 先删除中间表数据
            role.setPermissions(permissionSet);
        }
        // 添加一级菜单
        LinkedHashSet<Menu> menuList = menuDao.findMenuListByRoleId(role.getId());
        for (Menu menu : menuList) {
            // 将二级菜单封装到一级菜单中
            List<Menu> childList = menuDao.findChildByParentRoleId(menu.getId());
            menu.setChildren(childList);
        }
        // 将菜单信息保存到角色
        if (menuList != null && menuList.size() > 0) {
            role.setMenus(menuList);
        }
        return role;
    }

    /**
     * 查询所有角色
     * @return
     */
    @Override
    public List<Role> findAll() {
        return roleDao.selectAll();
    }

    /**
     * 分页条件查询
     * @param searchMap
     * @param page
     * @param size
     * @return
     */
    @Override
    public Page<Role> queryPageByExample(Map<String, Object> searchMap, int page, int size) {
        PageHelper.startPage(page, size);
        Example example = createExample(searchMap);
        return (Page<Role>) roleDao.selectByExample(example);
    }

    /**
     * 根据username查询对应的角色相关信息
     * @param username
     * @return
     */
    @Override
    public List<Role> findRoleByUsername(String username) {
        // 判断是否存在该用户
        Example example = new Example(Employee.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username", username);
        Employee employee = employeeMapper.selectOneByExample(example);
        if (employee == null) {
            throw new RuntimeException("用户不存在");
        }
        // 根据用户id查中间表获取角色列表
        List<Role> roleList = employeeMapper.findRoleByEmployeeId(employee.getId());
        for (Role role : roleList) {
            // 将权限和菜单封装到对应的角色
            Set<Permission> permissionSet = permissionDao.findPermissionByRoleId(role.getId());
            role.setPermissions(permissionSet);
            // 查询角色菜单中间表数据
            LinkedHashSet<Menu> menuLinkedHashSet = menuDao.findMenuListByRoleId(role.getId());
            for (Menu menu : menuLinkedHashSet) {
                // 将菜单插入role
                List<Menu> childList = menuDao.findChildByParentRoleId(menu.getId());
                menu.setChildren(childList);
            }
            role.setMenus(menuLinkedHashSet);
        }
        employee.setRoleList(roleList);
        return roleList;
    }

    /**
     * 查询条件
     * @param searchMap
     * @return
     */
    private Example createExample(Map<String, Object> searchMap) {
        Example example = new Example(Role.class);
        Example.Criteria criteria = example.createCriteria();
        // name
        if (searchMap.get("name") != null && !"".equals(searchMap.get("name"))) {
            criteria.andEqualTo("name", searchMap.get("name"));
        }
        // keyword
        if (searchMap.get("keyword") != null && !"".equals(searchMap.get("keyword"))) {
            criteria.andEqualTo("keyword", searchMap.get("keyword"));
        }
        return example;
    }
}
